package com.yibo.user.service.user;

import com.yibo.redis.RedisCommand;
import com.yibo.redis.util.lock.LockUtil;
import com.yibo.redis.util.lock.RedisLock;
import com.yibo.support.helper.Assert;
import com.yibo.support.helper.JsonHelper;
import com.yibo.support.helper.TimeHelper;
import com.yibo.support.inter.Command;
import com.yibo.db.user.entity.User;
import com.yibo.db.user.entity.UserInfo;
import com.yibo.db.user.entity.UserLevel;
import com.yibo.db.user.mapper.user.UserMapper;
import com.yibo.db.user.mapper.userinfo.UserInfoMapper;
import com.yibo.db.user.mapper.userlev.UserLevelMapper;
import com.yibo.user.object.YBUser;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

import static com.yibo.support.constant.MsgConstant.NOT_LOGIN;
import static com.yibo.support.constant.YBConstant.*;

/**
 * 查询登陆用户命令,
 *
 * 主要逻辑，每过一分钟用户可以手动的通过刷新页面的方式，查询正在登陆的用户信息，
 * 用户信息会先从redis中查询，然后会在异步中将最新的用户信息放到redis中，用户下次刷新时，会有新的信息
 *
 *
 * @author zhanglei
 */
public class QueryLoginUserCommand implements Command<YBUser> {

    private static final String USER_LOCK = "yibo:user:lock:";

    //返回值
    private YBUser result;

    /**
     * token
     */
    private String token;

    @Override
    public YBUser execute() {
        initIp();
        Assert.notEmpty(NOT_LOGIN,token);

        RedisCommand redisCommand = getBean(RedisCommand.class);
        this.result = redisCommand.get(YIBO_USER_REDIS_PREFIX_TOKEN+this.token,YBUser.class);
        Assert.notEmpty(NOT_LOGIN,this.result);

        changeLoginUserRedis();
        return this.result;
    }



    private void changeLoginUserRedis(){

        String lastQueryTime = this.result.getLastQueryTime();
        //每一分钟可以手动刷新一次
        if(TimeHelper.betweenSeconds(lastQueryTime,TimeHelper.getNow()) > 60){
            final String userId = result.getUserId();
            final String token = result.getToken();
            final String ip = result.getIp();
            final String lastLoginTime = result.getLastLoginTime();
            UserInfoMapper infoMapper = getBean(UserInfoMapper.class);
            UserMapper userMapper = getBean(UserMapper.class);
            UserLevelMapper userLevelMapper = getBean(UserLevelMapper.class);
            RedisCommand redisCommand= getBean(RedisCommand.class);
            new Thread(()->{
                User user = userMapper.selectById(userId);
                UserInfo userInfo = infoMapper.selectById(userId);
                UserLevel level = userLevelMapper.selectById(userId);
                YBUser ybUser = new YBUser()
                        .setUserId(user.getUserId())
                        .setUserName(user.getUserName())
                        .setIp(ip)
                        .setExtInfo(userInfo)
                        .setToken(token)
                        .setLastLoginTime(lastLoginTime)
                        .setLastQueryTime(TimeHelper.getNow())
                        .setUserLevel(level);

                RedisLock redisLock = LockUtil.getLock(USER_LOCK + user.getUserId());
                try {
                    if (redisLock.acquire()) {
                        redisCommand.remove(YIBO_USER_REDIS_PREFIX_USER_ID+userId);
                        redisCommand.remove(YIBO_USER_REDIS_PREFIX_TOKEN+token);
                        redisCommand.set(YIBO_USER_REDIS_PREFIX_USER_ID+userId, JsonHelper.toJson(ybUser));
                        redisCommand.set(YIBO_USER_REDIS_PREFIX_TOKEN+token, JsonHelper.toJson(ybUser));
                    }
                }finally {
                    redisLock.release();
                }
            }).start();
        }
    }




    private void  initIp(){
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            this.token = request.getHeader(TOKEN);
        }catch (Exception e){
            //不抛出异常
        }
    }
}
